package com.shuai;

import com.shuai.config.RegistryConfig;
import com.shuai.config.RpcConfig;
import com.shuai.constants.RpcConstant;
import com.shuai.registry.Registry;
import com.shuai.registry.RegistryFactory;
import com.shuai.utils.ConfigUtils;
import lombok.extern.slf4j.Slf4j;

/** RPC 框架应用 存放了项目全局用到的变量。双检锁单例模式实现 */
@Slf4j
public class RpcApplication {

  private static volatile RpcConfig rpcConfig;

  /** 私有构造函数，防止外界实例化 */
  private RpcApplication() {}

  /**
   * 框架初始化，支持传入自定义配置
   *
   * @param newRpcConfig
   */
  public static void setNewRpcConfig(RpcConfig newRpcConfig) {
    rpcConfig = newRpcConfig;
    log.info("rpc init, config = {}", newRpcConfig.toString());
    // 注册中心初始化 默认Zookeeper
    RegistryConfig registryConfig = rpcConfig.getRegistryConfig();
    Registry registry = RegistryFactory.getInstance(registryConfig.getRegistry());
    registry.init(registryConfig);
    log.info("registry init, config = {}", registryConfig);
  }

  /** 初始化 */
  public static void init() {
    RpcConfig localRpcConfig = null;
    try {
      localRpcConfig =
          ConfigUtils.loadConfigProperties(RpcConfig.class, RpcConstant.DEFAULT_CONFIG_PREFIX);
    } catch (Exception e) {
      // 配置加载失败，使用默认值
      localRpcConfig = new RpcConfig();
    }
    setNewRpcConfig(localRpcConfig);
  }

  /**
   * 加载特定的环境配置文件
   *
   * @param environment
   */
  public static void init(String environment) {
    RpcConfig localRpcConfig = null;
    try {
      localRpcConfig =
          ConfigUtils.loadConfigWithProperties(
              RpcConfig.class, RpcConstant.DEFAULT_CONFIG_PREFIX, environment);
    } catch (Exception e) {
      // 配置加载失败，使用默认值
      localRpcConfig = new RpcConfig();
    }
    setNewRpcConfig(localRpcConfig);
  }

  /**
   * 获取rpc配置文件 application.properties
   *
   * @return
   */
  public static RpcConfig getRpcConfig() {
    if (rpcConfig == null) {
      synchronized (RpcApplication.class) {
        if (rpcConfig == null) {
          init();
        }
      }
    }
    return rpcConfig;
  }

  /**
   * 获取特定环境rpc配置文件 application-dev.properties application-test.properties
   * application-prod.properties
   *
   * @param environment
   * @return
   */
  public static RpcConfig getRpcConfig(String environment) {
    if (rpcConfig == null) {
      synchronized (RpcApplication.class) {
        if (rpcConfig == null) {
          init(environment);
        }
      }
    }
    return rpcConfig;
  }
}
